本篇同步發文在個人Blog: 一袋.NET要扛幾樓?打造容器化的ASP.NET Core網站!系列文章 - (18) 建立購物車系統 - 1
開啟VS,在RPGShop方案的src/Services的方案資料夾,加入新的ASP.NET Core專案,專案名稱為CartApi,選擇專案類型Api,不要用Docker和HTTPS。
在CartApi專案右鍵=>選擇[管理NuGet套件],安裝Redis的相關套件,包含這項:
傳統購物網站大部分使用Session紀錄目前連線者的購物車內容,但缺點有幾項:
採用Redis的話,可以將Redis架在別的伺服器,且能依照Client的Id存取資料
新增Models資料夾並新增Cart和CartItem兩個類別,主要紀錄購物車的內容:
using System.Collections.Generic;
namespace CartApi.Models
{
public class Cart
{
public string BuyerId { get; set; }
public List<CartItem> Items { get; set; }
public Cart(string cartId)
{
BuyerId = cartId;
Items = new List<CartItem>();
}
}
}
namespace CartApi.Models
{
public class CartItem
{
public string Id { get; set; }
public string ProductId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public decimal OldUnitPrice { get; set; }
public int Quantity { get; set; }
public string PictureUrl { get; set; }
}
}
在Models資料夾新增ICartRepository介面和CartRepository,包含購物車內容的更新、刪除、讀取和取得所有使用者的Id列表。實作類別需注入Redis的物件,並針對Client的Id作為Redis的Key,來存取購物車的資料。
.
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CartApi.Models
{
public interface ICartRepository
{
Task<Cart> GetCartAsync(string cartId);
IEnumerable<string> GetUsers();
Task<Cart> UpdateCartAsync(Cart basket);
Task<bool> DeleteCartAsync(string id);
}
}
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using StackExchange.Redis;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CartApi.Models
{
public class CartRepository : ICartRepository
{
private readonly ILogger<CartRepository> _logger;
private readonly ConnectionMultiplexer _redis;
private readonly IDatabase _database;
public CartRepository(ILogger<CartRepository> logger, ConnectionMultiplexer redis)
{
_logger = logger;
_redis = redis;
_database = redis.GetDatabase();
}
public async Task<Cart> GetCartAsync(string cartId)
{
var data = await _database.StringGetAsync(cartId);
if (data.IsNullOrEmpty)
{
return null;
}
return JsonConvert.DeserializeObject<Cart>(data);
}
public IEnumerable<string> GetUsers()
{
var server = GetServers();
var data = server.Keys();
return data?.Select(k => k.ToString());
}
private IServer GetServers()
{
var endpoint = _redis.GetEndPoints();
return _redis.GetServer(endpoint.First());
}
public async Task<Cart> UpdateCartAsync(Cart basket)
{
var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket));
if (!created)
{
_logger.LogInformation("Problem occur persisting the item");
return null;
}
return await GetCartAsync(basket.BuyerId);
}
public async Task<bool> DeleteCartAsync(string id)
{
return await _database.KeyDeleteAsync(id);
}
}
}